﻿/**
 *	\file		reg_path.hxx
 *	\date		(2014-12-30 17:31:00)/(2014-12-30 17:31:00)
 *-----------------------------------------------------------------------------
 *	\brief
 *	\version	1.0.0.1
 *	\author		Nick Shallery	(nicknide@gmail.com)
 *	\copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#if			!defined(__LOLIX__SAMSARA__REG_PATH__HXX__NICK__K_IN_G__)
#define		__LOLIX__SAMSARA__REG_PATH__HXX__NICK__K_IN_G__
#include	<lolix/lolix.h>


#if			defined(LOLIX_DEF__PLATFORM_X64)

struct _RegBack
{
	lolix::lx_u64 rip;
	//lolix::lx_u64 rax;
	lolix::lx_u64 rbx;
	//lolix::lx_u64 rcx;
	//lolix::lx_u64 rdx;
	lolix::lx_u64 rsi;
	lolix::lx_u64 rdi;
	lolix::lx_u64 rbp;
	lolix::lx_u64 rsp;
	//lolix::lx_u64 r8;
	//lolix::lx_u64 r9;
	//lolix::lx_u64 r10;
	//lolix::lx_u64 r11;
	lolix::lx_u64 r12;
	lolix::lx_u64 r13;
	lolix::lx_u64 r14;
	lolix::lx_u64 r15;
	lolix::lx_u64 mxcsr;
	//int_128_buf		xmm[8];
};
STATIC_ASSERT(sizeof(_RegBack) == 88);	//	这个值需要和汇编代码中的地方配对	_RegBack$Size

static_assert(sizeof(_RegBack) == 11*8, "");
#elif		defined(LOLIX_DEF__PLATFORM_X86)

struct _RegBack
{
	//lolix::lx_u32 eax;
	lolix::lx_u32 eip;
	lolix::lx_u32 ebx;
	//lolix::lx_u32 ecx;
	//lolix::lx_u32 edx;
	lolix::lx_u32 esi;
	lolix::lx_u32 edi;
	lolix::lx_u32 ebp;
	lolix::lx_u32 esp;
};
STATIC_ASSERT(sizeof(_RegBack) == 24);	//	这个值需要和汇编代码中的地方配对	_RegBack$Size

#endif	//	defined(LOLIX_DEF__PLATFORM_X86)

/**
* \brief	记录执行上下文信息并调用指定函数
* \arg	callback	回调的信息数据
* \arg	usrptr		回调时的用户信息
**/
extern "C" void LOLIX_CALL push_reg(void (__stdcall* callback)(_RegBack*, void*), void* usrptr);

/**
* \brief	记录当前执行上下文信息
* \arg	rg	待记录的信息
**/
extern "C" void* LOLIX_CALL save_context(_RegBack* rg);

/**
* \brief	回到保存的寄存器状态
* \arg	rb	已经保存过的寄存器信息
* \arg	rtv	返回到寄存器状态后的返回值
**/
extern "C" void LOLIX_CALL pop_reg(_RegBack const* rb, void* rtv);

/**
* \brief	在指定的堆栈上下文中调用函数
* \arg	stack_start	堆栈起始位置(低地址)
* \arg	stack_size	堆栈的大小
* \arg	func		需要在此堆栈调用的函数
* \arg	usrptr		需要调用的函数的参数
**/
extern "C" void LOLIX_CALL run_with_stack(void* stack_start, lolix::size_type stack_size, void (__stdcall* func)(void*), void* usrptr);

/**
* \brief 记录下当前栈顶指针位置
* \return	栈顶指针(r|e)sp的位置
**/
extern "C" void* LOLIX_CALL get_stack(void);

#endif	//	!defined(__LOLIX__SAMSARA__REG_PATH__HXX__NICK__K_IN_G__)
